package com.byit.jwt.utils;

import com.byit.jwt.ann.JwtUser;
import com.byit.jwt.domain.JwtSession;
import com.byit.jwt.lifecycle.JwtSessionLifecycleAspect;
import com.byit.utils.RedisUtil;
import com.byit.utils.SpringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

import javax.servlet.http.HttpServletRequest;

/**
 * Jwt User参数解析器
 *
 * @author marker
 **/
@Slf4j
@ControllerAdvice
public class JwtUserHandler implements HandlerMethodArgumentResolver {


    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        if (parameter.hasParameterAnnotation(JwtUser.class)) {
            return true;
        }
        return false;
    }

    @Override
    public Object resolveArgument(MethodParameter parameter,
                                  ModelAndViewContainer mavContainer, NativeWebRequest webRequest,
                                  WebDataBinderFactory binderFactory) throws Exception {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder
                .currentRequestAttributes()).getRequest();

        RedisUtil redisUtil = SpringUtil.getBean(RedisUtil.class);

        String authorization = request.getHeader("Authorization");
        if (authorization != null) {
            JwtSession session = JWTUtil.getSession(authorization);
            if (session != null) {
                String token = (String) redisUtil.get(JwtSessionLifecycleAspect.KEY + session.userId());
                if (authorization.equals(token)) { // 验证服务器的Session 与提交的Session一致。
                    session.token(token);
                    return session;
                }
            }
        }
        return JwtSession.builder();
    }
}
